Imports Clo = Enhancements.Core.Logging
Imports Ere = Enhancements.Basic.RegularExpressions
Imports Exe = Enhancements.Basic.Expressions
Imports Exo = Enhancements.Basic.Expressions.Operators
Imports Gen = System.Collections.Generic
Imports Glo = System.Globalization
Imports Iou = System.IO
Imports Ref = System.Reflection
Imports Reg = System.Text.RegularExpressions
Imports Sys = System
Imports Tex = System.Text
Imports Xsd = System.Xml.Schema
Imports W3c = System.Xml

Namespace Enhancements.Basic.Expressions.Operators
    ''' <summary>Represents a token extracted from an expression that has an operator.</summary>
    <Serializable()> _
    Public MustInherit Class [Operator]
        Inherits Exe.Token

        Friend Sub New(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32, ByVal _expressionEndIndex As Sys.Int32)
            MyBase.New(_expression, _expressionBeginIndex, _expressionEndIndex)
        End Sub

        Private Shared __OperatorsSorted As Gen.Dictionary(Of System.String, Sys.Type) = Nothing
        Friend Shared Function ___OperatorsSortedGet() As Gen.Dictionary(Of System.String, Sys.Type)
            If __OperatorsSorted.IsNull("__OperatorsSorted", False) Then
                Dim _operatorsSortedDictionary As Gen.SortedDictionary(Of System.String, Sys.Type) = New Gen.SortedDictionary(Of System.String, Sys.Type)()
                _operatorsSortedDictionary.Add(___Texts.ToUpper([And].Representation), GetType([And]))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Asterisk.Representation), GetType(Asterisk))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Caret.Representation), GetType(Caret))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Different.Representation), GetType(Different))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Operators.Equals.Representation), GetType(Equals))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(HigherOrEquals.Representation), GetType(HigherOrEquals))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(HigherThan.Representation), GetType(HigherThan))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(LowerOrEquals.Representation), GetType(LowerOrEquals))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(LowerThan.Representation), GetType(LowerThan))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Minus.Representation), GetType(Minus))
                _operatorsSortedDictionary.Add(___Texts.ToUpper([Not].Representation), GetType([Not]))
                _operatorsSortedDictionary.Add(___Texts.ToUpper([Or].Representation), GetType([Or]))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Percent.Representation), GetType(Percent))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Plus.Representation), GetType(Plus))
                _operatorsSortedDictionary.Add(___Texts.ToUpper(Slash.Representation), GetType(Slash))
                __OperatorsSorted = New Gen.Dictionary(Of System.String, Sys.Type)()
                For _counter As Sys.Int32 = _operatorsSortedDictionary.Count - 1 To 0 Step -1
                    __OperatorsSorted.Add(_operatorsSortedDictionary.ElementAt(_counter).Key, _operatorsSortedDictionary.ElementAt(_counter).Value)
                Next _counter
            End If

            Return __OperatorsSorted
        End Function

        Private Shared Function __Parse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32) As Sys.Object
            Dim _returnValue As Sys.Object = Nothing
            Dim _and As [And] = Nothing
            Dim _asterisk As Asterisk = Nothing
            Dim _caret As Caret = Nothing
            Dim _different As Different = Nothing
            Dim _equals As Equals = Nothing
            Dim _higherOrEquals As HigherOrEquals = Nothing
            Dim _higherThan As HigherThan = Nothing
            Dim _lowerOrEquals As LowerOrEquals = Nothing
            Dim _lowerThan As LowerThan = Nothing
            Dim _minus As Minus = Nothing
            Dim _not As [Not] = Nothing
            Dim _or As [Or] = Nothing
            Dim _percent As Percent = Nothing
            Dim _plus As Plus = Nothing
            Dim _slash As Slash = Nothing
            For Each _operator As Sys.Type In ___OperatorsSortedGet().Values.ToArray()
                If _operator.Is("_operator", GetType([And]), "GetType([And])", False) AndAlso [And].TryParse(_expression, _expressionBeginIndex, _and).IsTrue("[And].TryParse(_expression, _expressionBeginIndex, _and)", False) Then
                    _returnValue = _and
                    Exit For
                Else
                    If _operator.Is("_operator", GetType(Asterisk), "GetType(Asterisk)", False) AndAlso Asterisk.TryParse(_expression, _expressionBeginIndex, _asterisk).IsTrue("Asterisk.TryParse(_expression, _expressionBeginIndex, _asterisk)", False) Then
                        _returnValue = _asterisk
                        Exit For
                    Else
                        If _operator.Is("_operator", GetType(Caret), "GetType(Caret)", False) AndAlso Caret.TryParse(_expression, _expressionBeginIndex, _caret).IsTrue("Caret.TryParse(_expression, _expressionBeginIndex, _caret)", False) Then
                            _returnValue = _caret
                            Exit For
                        Else
                            If _operator.Is("_operator", GetType(Different), "GetType(Different)", False) AndAlso Different.TryParse(_expression, _expressionBeginIndex, _different).IsTrue("Different.TryParse(_expression, _expressionBeginIndex, _different)", False) Then
                                _returnValue = _different
                                Exit For
                            Else
                                If _operator.Is("_operator", GetType(Equals), "GetType(Equals)", False) AndAlso Exo.Equals.TryParse(_expression, _expressionBeginIndex, _equals).IsTrue("Equals.TryParse(_expression, _expressionBeginIndex, _equals)", False) Then
                                    _returnValue = _equals
                                    Exit For
                                Else
                                    If _operator.Is("_operator", GetType(HigherOrEquals), "GetType(HigherOrEquals)", False) AndAlso HigherOrEquals.TryParse(_expression, _expressionBeginIndex, _higherOrEquals).IsTrue("HigherOrEquals.TryParse(_expression, _expressionBeginIndex, _higherOrEquals)", False) Then
                                        _returnValue = _higherOrEquals
                                        Exit For
                                    Else
                                        If _operator.Is("_operator", GetType(HigherThan), "GetType(HigherThan)", False) AndAlso HigherThan.TryParse(_expression, _expressionBeginIndex, _higherThan).IsTrue("HigherThan.TryParse(_expression, _expressionBeginIndex, _higherThan)", False) Then
                                            _returnValue = _higherThan
                                            Exit For
                                        Else
                                            If _operator.Is("_operator", GetType(LowerOrEquals), "GetType(LowerOrEquals)", False) AndAlso LowerOrEquals.TryParse(_expression, _expressionBeginIndex, _lowerOrEquals).IsTrue("LowerOrEquals.TryParse(_expression, _expressionBeginIndex, _lowerOrEquals)", False) Then
                                                _returnValue = _lowerOrEquals
                                                Exit For
                                            Else
                                                If _operator.Is("_operator", GetType(LowerThan), "GetType(LowerThan)", False) AndAlso LowerThan.TryParse(_expression, _expressionBeginIndex, _lowerThan).IsTrue("LowerThan.TryParse(_expression, _expressionBeginIndex, _lowerThan)", False) Then
                                                    _returnValue = _lowerThan
                                                    Exit For
                                                Else
                                                    If _operator.Is("_operator", GetType(Minus), "GetType(Minus)", False) AndAlso Minus.TryParse(_expression, _expressionBeginIndex, _minus).IsTrue("Minus.TryParse(_expression, _expressionBeginIndex, _minus)", False) Then
                                                        _returnValue = _minus
                                                        Exit For
                                                    Else
                                                        If _operator.Is("_operator", GetType([Not]), "GetType([Not])", False) AndAlso [Not].TryParse(_expression, _expressionBeginIndex, _not).IsTrue("[Not].TryParse(_expression, _expressionBeginIndex, _not)", False) Then
                                                            _returnValue = _not
                                                            Exit For
                                                        Else
                                                            If _operator.Is("_operator", GetType([Or]), "GetType([Or])", False) AndAlso [Or].TryParse(_expression, _expressionBeginIndex, _or).IsTrue("[Or].TryParse(_expression, _expressionBeginIndex, _or)", False) Then
                                                                _returnValue = _or
                                                                Exit For
                                                            Else
                                                                If _operator.Is("_operator", GetType(Percent), "GetType(Percent)", False) AndAlso Percent.TryParse(_expression, _expressionBeginIndex, _percent).IsTrue("Percent.TryParse(_expression, _expressionBeginIndex, _percent)", False) Then
                                                                    _returnValue = _percent
                                                                    Exit For
                                                                Else
                                                                    If _operator.Is("_operator", GetType(Plus), "GetType(Plus)", False) AndAlso Plus.TryParse(_expression, _expressionBeginIndex, _plus).IsTrue("Plus.TryParse(_expression, _expressionBeginIndex, _plus)", False) Then
                                                                        _returnValue = _plus
                                                                        Exit For
                                                                    Else
                                                                        If _operator.Is("_operator", GetType(Slash), "GetType(Slash)", False) AndAlso Slash.TryParse(_expression, _expressionBeginIndex, _slash).IsTrue("Slash.TryParse(_expression, _expressionBeginIndex, _slash)", False) Then
                                                                            _returnValue = _slash
                                                                            Exit For
                                                                        End If
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next _operator
            If Assert.IsNull(_returnValue, "_returnValue", False) Then
                _returnValue = OperatorParseException.___Create(_expression, _expressionBeginIndex)
            End If

            Return _returnValue
        End Function

        ''' <summary>Parses an expression for an operator starting by a begin index.</summary>
        ''' <param name="_expression">Expression to parse.</param>
        ''' <param name="_expressionBeginIndex">Expression begin index to use.</param>
        ''' <exception cref="OperatorParseException">The operation did not produce a valid token.</exception>
        ''' <returns> </returns>
        Public Shared Function Parse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32) As [Operator]
            Dim _returnValue As Sys.Object = __Parse(_expression, _expressionBeginIndex)
            If Assert.IsOfType(_returnValue, "_returnValue", GetType(OperatorParseException), False) Then
                OperatorParseException.___Throw(CType(_returnValue, OperatorParseException))
            End If

            Return CType(_returnValue, [Operator])
        End Function

        ''' <summary>Tries to parse an expression for an operator starting by a begin index.</summary>
        ''' <param name="_expression">Expression to parse.</param>
        ''' <param name="_expressionBeginIndex">Expression begin index to use.</param>
        ''' <param name="_result">The result of the operation if possible. If not, null is returned.</param>
        ''' <returns> </returns>
        Public Shared Function TryParse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32, ByRef _result As [Operator]) As System.Boolean

            Dim _returnValue As System.Boolean = False
            Dim _dummy As Sys.Object = __Parse(_expression, _expressionBeginIndex)
            If Assert.IsOfType(_dummy, "_dummy", GetType(OperatorParseException), False) Then
                _result = Nothing
                _returnValue = False
            Else
                _result = CType(_dummy, [Operator])
                _returnValue = True
            End If

            Return _returnValue
        End Function

        Friend Shared Function ___TryParse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32, ByVal _operatorType As Sys.Type, ByRef _result As [Operator]) As System.Boolean
            Dim _returnValue As System.Boolean = False
            _result = Nothing
            If _expression.IsNullNot("_expression", False) AndAlso _expression.IsEmptyNot("_expression", False) AndAlso _expressionBeginIndex.IsInRange("_expressionBeginIndex", 0, _expression.Length - 1, False) Then
                If _operatorType.IsNullNot("_operatorType", False) Then
                    If _operatorType.IsDerivedOf("_operatorType", GetType([Operator]), False) Then
                        If Assert.IsSealed(_operatorType, "_operatorType", False) Then
                            Dim _operatorTypeTryParse As Ref.MethodInfo = _operatorType.GetMethod("TryParse")
                            Dim _dummy(3 - 1) As Sys.Object
                            _dummy(0) = _expression
                            _dummy(1) = _expressionBeginIndex
                            _dummy(2) = _result
                            _returnValue = CType(_operatorTypeTryParse.Invoke(Nothing, _dummy), System.Boolean)
                            _result = CType(_dummy(2), [Operator])
                        End If
                    End If
                End If
            End If

            Return _returnValue
        End Function

    End Class
End Namespace
